#include "GameGalaxy.h"

GameGalaxy::GameGalaxy(
	WINAPP*  a_app,
	WINFPS*  a_fps,
	WINTIME* a_time,
	D3DF*    a_d3d,
	DINF*    a_din,
	bool     a_renew)
{
	m_app  = a_app;
	m_fps  = a_fps;
	m_time = a_time;
	m_d3d  = a_d3d;
	m_din  = a_din;

	strcpy_s(m_name,32,"GameGalaxy");
	m_selfId = GAMEGALAXY;
	m_swapId = GAMEGALAXY;
	m_completed = false;
	m_renew = false;
}

void GameGalaxy::init()
{
	//create and set effect
	m_d3d->createEffect(&m_effect,"effects/ambient.fx");
	m_d3d->setEffect(&m_effect);

	//obtain system data
	m_sysData = (gData*)m_data;

	//init quadrant object
	for(int i = 0; i < m_sysData->m_quadAmt; i++)
	{
		V2DF pos = m_sysData->m_quadPos[i];

		Physic_Object_Frame frame;
		frame.m_radius   = m_sysData->m_quadRad[i];
		frame.m_position = Vector3(pos.x,0.0f,pos.y);

		gObject* quad = new gObject;
		quad->init(FRAMEWORKS_MEM_REG,&m_world);
		quad->initMesh("meshes/plane.x",V3D_ZERO,V3D_ZERO,
			V3D_ONES*(frame.m_radius*0.1f),V3D_ZERO);
		quad->initTexture("textures/circleB.png");
		quad->initPhysics(m_world.CreateObject(&frame));
		quad->update();
		m_quads.insertBack(quad);
	}
	
	//init player
	Physic_Object_Frame frame;
	frame.m_maxSpeed = 200.0f;
	frame.m_drag     = 25.0f;
	frame.m_radius   = m_sysData->m_playerRad;

	m_player.init(FRAMEWORKS_MEM_REG,&m_world);
	m_player.initMesh("meshes/player.x",V3D_ZERO,V3D_ZERO,V3D_ONES,V3D_ZERO);
	m_player.initTexture("textures/tex_player.png");
	m_player.initPhysics(m_world.CreateObject(&frame));
	m_player.update();

	//init camera
	m_camera.init(FRAMEWORKS_MEM_REG);
	m_camera.initCamera(V3D_ZERO,180.0f,-CAMR_ROT,WINW/WINH,CAMR_NER,CAMR_FAR);
	m_camera.setZMinMax(CAMR_ZMN,CAMR_ZMX);
	m_camera.setDis(CAMR_DIS);
	m_camera.trigMove();
	m_camera.attach(m_player.ptrTrn(),V3D_ZERO);

	//init gui interface
	m_energy.init(FRAMEWORKS_MEM_REG);
	m_energy.initBar(
		"textures/health_back.png",
		"textures/health_bar.png",
		"textures/health_fore.png",
		V2DF(WINW-64,WINH-32),
		V2DF(7,-3));

	m_shield.init(FRAMEWORKS_MEM_REG);
	m_shield.initSlider(
		"textures/slider_bar.png",
		"textures/slider_btn.png",
		"textures/icon_shield.png",
		"textures/info_shield.png",
		V2DF(WINW-244,WINH-94),
		V2DF(-2,-90),
		V2DF(72,-150));

	m_weapon.init(FRAMEWORKS_MEM_REG);
	m_weapon.initSlider(
		"textures/slider_bar.png",
		"textures/slider_btn.png",
		"textures/icon_weapon.png",
		"textures/info_weapon.png",
		V2DF(WINW-196,WINH-94),
		V2DF(-2,-90),
		V2DF(24,-150));

	m_boost.init(FRAMEWORKS_MEM_REG);
	m_boost.initSlider(
		"textures/slider_bar.png",
		"textures/slider_btn.png",
		"textures/icon_booster.png",
		"textures/info_booster.png",
		V2DF(WINW-148,WINH-94),
		V2DF(-2,-90),
		V2DF(-24,-150));

	m_hyper.init(FRAMEWORKS_MEM_REG);
	m_hyper.initSlider(
		"textures/slider_bar.png",
		"textures/slider_btn.png",
		"textures/icon_hyper.png",
		"textures/info_hyper.png",
		V2DF(WINW-100,WINH-94),
		V2DF(-2,-90),
		V2DF(-72,-150));

	m_gui.init(FRAMEWORKS_MEM_REG);
	m_guiInfo.init(FRAMEWORKS_MEM_REG);
	m_guiLog.init(FRAMEWORKS_MEM_REG);
	m_guiWeapons.init(FRAMEWORKS_MEM_REG);

	m_gui.initTexture("textures/gui.png",TEX_TL,V2D_ZERO,V2D_ONES,0.0f);
	m_guiInfo.initTexture("textures/info.png", TEX_TL, V2D_ZERO, V2D_ONES, 0.0f);
	m_guiLog.initTexture("textures/log.png", TEX_LC, V2DF(0,320), V2D_ONES, 0.0f);
	m_guiWeapons.initTexture("textures/weapons.png", TEX_BL, V2DF(0,720), V2D_ONES, 0.0f);

	m_gui.update();
	m_guiInfo.update();
	m_guiLog.update();
	m_guiWeapons.update();

	//init background
	m_grid.init(FRAMEWORKS_MEM_REG);
	m_grid.initMesh(
		"meshes/plane.x",
		V3D_ZERO,V3D_Y*-GRID_DEP,
		V3D_ONES*GALX_RAD*0.1f,
		V3D_ZERO);
	m_grid.initTexture("textures/grid.png");
	m_grid.update();

	m_circ.init(FRAMEWORKS_MEM_REG);
	m_circ.initMesh("meshes/plane.x",V3D_ZERO,V3D_Y*-8.0f,V3D_ONES*GALX_RAD*0.1f,V3D_ZERO);
	m_circ.initTexture("textures/circleA.png");
	m_circ.update();

	for(int i = 0; i < 4; i++)
	{
		float dp = (STAR_SCL*(5.0f-(i+1.0f)))+STAR_SCL;
		float rt = 90.0f*i;

		m_back[i].init(FRAMEWORKS_MEM_REG);
		m_back[i].initMesh(
			"meshes/plane.x",
			V3D_ZERO,
			V3DF(0,-dp,dp),
			V3D_ONES*STAR_SCL,
			V3DF(-CAMR_ROT,rt,0));
		m_back[i].initTexture("textures/stars.png");
		m_back[i].update();
	}

	//calc player positioning
	V3DF  dir = (m_quads[0]->getPos()-m_player.getPos()).normal();
	float rot = DEGREE(polarAngleXZ(dir))+180.0f;
	m_sysData->m_playerDir = dir;
	m_sysData->m_playerRot = rot;
	m_sysData->m_quadId = 0;

	//flag for immediate state change
	m_swapId = GAMEQUADRANT;
	m_completed = true;
}

void GameGalaxy::reset()
{
	//calc player position to galaxy space
	V3DF  pdir(m_sysData->m_playerDir);
	float prad = m_sysData->m_playerRad;
	V3DF  qpos(
		m_sysData->m_quadPos[m_sysData->m_quadId].x,0,
		m_sysData->m_quadPos[m_sysData->m_quadId].y);
	float qrad = m_sysData->m_quadRad[m_sysData->m_quadId];

	m_player.setEnergy(m_sysData->m_playerEnr);
	m_player.setVel(V3D_ZERO);
	m_player.setRot(V3DF(0,m_sysData->m_playerRot,0));
	m_player.setPos(qpos+(pdir*(qrad+(prad*2.0f))));

	m_energy.setPerc(m_sysData->m_playerEnr.m_energyRem);
	m_shield.setPerc(m_sysData->m_playerEnr.m_energyShield);
	m_weapon.setPerc(m_sysData->m_playerEnr.m_energyWeapon);
	m_boost.setPerc(m_sysData->m_playerEnr.m_energyBoost);
	m_hyper.setPerc(m_sysData->m_playerEnr.m_energyHyper);
}

void GameGalaxy::release()
{
	//release all memory
	LIST_MEM_DELETE(m_quads);
	m_quads.release();

	m_world.Shutdown();
}

void GameGalaxy::input()
{
	//acquire input
	m_din->acquire();

	//perform input checking
	m_shield.input();
	m_weapon.input();
	m_boost.input();
	m_hyper.input();

	m_player.input();
	m_camera.input();
	
	//go back to main menu if BACK key is hit
	if(m_din->keyPress(KEY_BACK))
	{m_swapId = GAMEMENU; m_completed = true;}
}

void GameGalaxy::update()
{
	//update physics world
	m_world.Update(m_time->getElapsed());

	//update objects
	guiUpdate();
	playerUpdate();
	collisionUpdate();

	//update camera
	m_camera.update();
}

void GameGalaxy::draw()
{
	m_d3d->drawBegin();

	//draw objects
	m_player.draw();

	//draw back objects
	for(int i = 0; i < 4; i++)
		m_back[i].draw();
	m_grid.draw();
	m_circ.draw();

	for(int i = 0; i < m_quads.size(); i++)
		m_quads[i]->draw();

	//draw gui
	m_gui.draw();
	m_guiInfo.draw();
	m_guiLog.draw();
	m_guiWeapons.draw();

	m_energy.draw();
	m_shield.draw();
	m_weapon.draw();
	m_boost.draw();
	m_hyper.draw();

	//draw text
	m_d3d->drawText(m_name,V2D_ZERO,CL_RED);
	m_d3d->drawText("Press BACK to GameMenu",V2DF(0,16),CL_RED);
	m_d3d->drawText("Hold SPACE at quadrant to enter QUADRANT space",V2DF(0,32),CL_RED);

	m_d3d->drawEnd();
}

void GameGalaxy::pre()
{
	//update fps and time
	m_fps->update();
	m_time->update();
}

void GameGalaxy::post()
{

}

void GameGalaxy::guiUpdate()
{
	m_energy.setPerc(m_player.getEnergy().m_energyRem);

	m_energy.update();
	m_shield.update();
	m_weapon.update();
	m_boost.update();
	m_hyper.update();

	m_player.getEnergy().m_energyShield = m_shield.getPerc();
	m_player.getEnergy().m_energyWeapon = m_weapon.getPerc();
	m_player.getEnergy().m_energyBoost  = m_boost.getPerc();
	m_player.getEnergy().m_energyHyper  = m_hyper.getPerc();
}

void GameGalaxy::playerUpdate()
{
	//bounce player off galaxy radius
	float rad = m_player.getRad();
	V2DF  pos(m_player.getPos().x,m_player.getPos().z);
	V2DF  vel(m_player.getVel().x,m_player.getVel().z);
	if(pos.distance(V2D_ZERO)+rad > m_sysData->m_galxRad)
	{
		V2DF pA = nrCrPoint(V2D_ZERO,GALX_RAD,pos);
		V2DF pB = nrCrPoint(pos,rad,pA);
		V2DF in = pB-pA;
		V2DF rf = ((in.perp().normal()*vel.dot(in.perp().normal()))*2.0f)-vel;

		V3DF p(pos.x,0,pos.y);
		V3DF i(in.x,0,in.y);
		V3DF v(rf.x,0,rf.y);

		m_player.setPos(p-i);
		m_player.setVel(v);
	}

	//handle quandrant detection
	Physic_Object* plyr = m_player.getPhysics();
	if(m_din->keyInput(KEY_SPACE)){
		for(int i = 0; i < m_quads.size(); i++)
		{
			if(plyr->collide(m_quads[i]->getPhysics()))
			{
				m_sysData->m_playerEnr = m_player.getEnergy();
				m_sysData->m_playerDir = (m_player.getPos()-m_quads[i]->getPos()).normal();
				m_sysData->m_playerRot = m_player.getRot().y;
				m_sysData->m_quadId = i;

				m_swapId = GAMEQUADRANT+i;
				m_completed = true;
				break;
			}
		}
	}

	//update player object
	m_player.update();
}

void GameGalaxy::collisionUpdate()
{
	//check for object collision
	for(int i = 0; i < m_quads.size(); i++)
	{
		gObject* obj = m_quads[i];

		obj->update();
		if(m_player.getPhysics()->collide(obj->getPhysics()))
		{
			float radA = m_player.getRad();
			V2DF  posA(m_player.getPos().x,m_player.getPos().z);
			V2DF  velA(m_player.getVel().x,m_player.getVel().z);

			float radB = obj->getRad();
			V2DF  posB(obj->getPos().x,obj->getPos().z);

			V2DF pA = nrCrPoint(posB,radB,posA);
			V2DF pB = nrCrPoint(posA,radA,pA);
			V2DF in = pB-pA;
			V2DF rf = ((in.perp().normal()*velA.dot(in.perp().normal()))*2.0f)-velA;

			V3DF p(posA.x,0,posA.y);
			V3DF i(in.x,0,in.y);
			V3DF v(rf.x,0,rf.y);

			m_player.setPos(p-i);
			m_player.setVel(v);
		}
	}
}